package jxtend.processor.eclipse.visitor.interceptor;

import java.util.List;

import jxtend.processor.eclipse.visitor.traverser.ASTNodeChildrenTraverser;
import jxtend.processor.exception.JxtendProcessorException;

import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.Scope;

@SuppressWarnings("restriction")
public class AlternativeTraverserASTNodeVisitorInterceptor extends ASTNodeVisitorInterceptorAdapter {
	private final List<ASTNodeChildrenTraverser> astNodeChildrenTraversers;

	public AlternativeTraverserASTNodeVisitorInterceptor(
			List<ASTNodeChildrenTraverser> astNodeChildrenTraversers) {
		super();
		this.astNodeChildrenTraversers = astNodeChildrenTraversers;
	}

	@Override
	public boolean interceptVisit(ASTNodeVisitorInterceptorContext interceptorChain, ASTNode node, Scope scope) {
		boolean result = super.interceptVisit(interceptorChain, node, scope);
		if (!result) {
			return false;
		}

		if (!(scope instanceof BlockScope)) {
			return result;
		}

		BlockScope blockScope = (BlockScope) scope;

		boolean foundTraverser = false;
		for (ASTNodeChildrenTraverser childrenTraverser : astNodeChildrenTraversers) {
			if (!childrenTraverser.isApplicable(node)) { continue; }

			if (foundTraverser) {
				throw new JxtendProcessorException(
						"Another ASTNodeChildrenTraverser already traversed the children of the node: %s", node);
			}
			foundTraverser = true;

			childrenTraverser.traverseChildren(node, interceptorChain.getASTVisitor(), blockScope);
		}

		return foundTraverser ? false : result;
	}
}
